if anon_general_functions_loaded then
	return
end

anon_general_functions_loaded = true

function HaveGlyph(id)
	for i = 1, GetNumGlyphSockets() do
		if select(4, GetGlyphSocketInfo(i)) == id then return true end
	end
	return false
end
	
function PlayerFacingTarget(Unit)
	if not UnitExists(Unit) or UnitIsUnit("player",Unit) then return false end

	local x1,y1,_,facing = PQR_UnitInfo(UnitGUID("player"))
	local x2,y2 = PQR_UnitInfo(UnitGUID(Unit))
	local yawAngle = atan2(y1 - y2, x1 - x2) - deg(facing)
	if yawAngle < 0 then yawAngle = yawAngle + 360 end

	return yawAngle > 90 and yawAngle < 270
end

function CheckAura(UnitID,SpellID,Filter,TimeLeft) 
	if not TimeLeft then TimeLeft = 0 end
	if type(SpellID) == "number" then SpellID = { SpellID } end 
	for i=1,#SpellID do 
		local spell, rank = GetSpellInfo(SpellID[i])
		if spell then
			local buff = select(7,UnitAura(UnitID,spell,rank,Filter)) 
			if buff and ( buff == 0 or buff - GetTime() > TimeLeft ) then return true end
		end
	end
end

function ValidDispel(t)
	local HasValidDispel = false
	local i = 1
	local debuff = UnitDebuff(t, i)
	while debuff do
		local debuffType = select(5, UnitDebuff(t, i))
		if debuffType == "Poison" or debuffType == "Disease" then
			HasValidDispel = true
		end
		i = i + 1
		debuff = UnitDebuff(t, i)
	end
	return HasValidDispel
end

--[[	
function inRange(t,spellID)
	if	UnitExists(t)
		and IsSpellInRange(GetSpellInfo(spellID),t) == 1
		and UnitCanAttack("player",t)
	then
		return true
	end
	
	return false
end
]]

function InRange(id, t)
    if IsSpellInRange(GetSpellInfo(id), t) == 1 then
        return true
    end  
    return false
end
function CanHeal(t)
	if	UnitInRange(t) and UnitCanCooperate("player",t) and not UnitIsEnemy("player",t) 
		and not UnitIsCharmed(t) and not UnitIsDeadOrGhost(t) and not PQR_IsOutOfSight(t) 
		and UnitExists(t)
	then
		return true
	end 
end

function CalculateHP(t)
  incomingheals = UnitGetIncomingHeals(t) and UnitGetIncomingHeals(t) or 0
  return 100 * ( UnitHealth(t) + incomingheals ) / UnitHealthMax(t)
end
 
function GroupInfo()
	members, group = { { Unit = "player", HP = CalculateHP("player") } }, { low = 0, tanks = { } } 
	group.type = IsInRaid() and "raid" or "party" 
	group.number = GetNumGroupMembers()
	for i=1,group.number do
		if CanHeal(group.type..i) then 
			local unit, hp = group.type..i, CalculateHP(group.type..i) 
			table.insert( members,{ Unit = unit, HP = hp } ) 
			if hp <= 85 then group.low = group.low + 1 end 
			if UnitGroupRolesAssigned(unit) == "TANK" then table.insert(group.tanks,unit) end 
		end
	end 
	if group.type == "raid" and #members > 1 then table.remove(members,1) end 
		table.sort(members, function(x,y) return x.HP < y.HP end)
		local customtarget = CanHeal("target") and "target" 
		if customtarget then table.sort(members, function(x) return UnitIsUnit(customtarget,x.Unit) end)
	end 
end

function HaveBuff(UnitID,SpellID,TimeLeft,Filter) 
	if not TimeLeft then TimeLeft = 0 end
	if type(SpellID) == "number" then SpellID = { SpellID } end 
	for i=1,#SpellID do 
		local spell, rank = GetSpellInfo(SpellID[i])
		if spell then
			local buff = select(7,UnitBuff(UnitID,spell,rank,Filter)) 
			if buff and ( buff == 0 or buff - GetTime() > TimeLeft ) then return true end
		end
	end
end

function HaveDebuff(UnitID,SpellID,TimeLeft,Filter) 
	if not TimeLeft then TimeLeft = 0 end
	if type(SpellID) == "number" then SpellID = { SpellID } end 
	for i=1,#SpellID do 
		local spell, rank = GetSpellInfo(SpellID[i])
		if spell then
			local debuff = select(7,UnitDebuff(UnitID,spell,rank,Filter)) 
			if debuff and ( debuff == 0 or debuff - GetTime() > TimeLeft ) then return true end
		end
	end
end

function SpellCheck(spell, target)
	if 	UnitExists(target) 
		and PQR_SpellAvailable(spell)
		and IsSpellInRange(GetSpellInfo(spell), target) == 1
		and UnitCanAttack("player", target) == 1  
	--	and not TargetImmune(target)
		and not UnitIsDeadOrGhost(target)
		and not PQR_IsOutOfSight(target, 1)
	then
		return true
	else
		return false
	end
end

function GetAuras(unitId, aura_type)
	local auraTable = {}
	
	for i = 1, 40 do
		name, _, _, count, _, duration, expire, _, _, _, spellId = UnitAura(unitId, i, aura_type)
			
		if name then
			tinsert(auraTable, { name = name, count = count, duration = duration, expire = expire, spellId = spellId })
		else
			break
		end
	end
	
	return auraTable
end

--[[
	choice: 1 - buff
			2 - debuff
]]
function LookUpAura(unitId, spellTbl, choice)
	if unitId then
		if type(spellTbl[1]) ~= "table" then spellTbl = { spellTbl } end
		
		local aura_type = ""
		
		if choice == 1 then
			aura_type = "HELPFUL"
		elseif choice == 2 then
			aura_type = "HARMFUL"
		end
		
		local auras = GetAuras(unitId, aura_type)

		for j = 1, #spellTbl do
			for i = 1, #auras do
				if spellTbl[j][auras[i].spellId] then
					return true
				end
			end
		end
	end
	
	return false
end

function UnitIsRooted(unitId)
	return LookUpAura(unitId, rootCC, 2)
end

function UnitIsDisabled(unitID)
	return LookUpAura(unitId, { stunCC, disorientCC, fearCC, horrorCC, randomStunCC, nCC, noCC }, 2)
end

function UnitNeedsDisarm(unitId)
	return LookUpAura(unitId, disarmList, 1)
end

function UnitIsFeared(unitId)
	return LookUpAura(unitId, fearCC, 2)
end

function UnitNeedsSlow(unitId)
	return not LookUpAura(unitId, slowCC, 2)
end

function UnitCanBeShattered(unitId)
	return LookUpAura(unitId, shatterList, 1)
end

function UnitIsImmuneToSlow(unitId)
	return LookUpAura(unitId, slowImmuneBuffList, 1)
end

function UnitIsImmuneToDamage(unitId)
	return LookUpAura(unitId, magicImmuneDebuffList, 2) or LookUpAura(unitId, immuneBuffList, 1)
end

function UnitIsImmuneToMagic(unitId)
	return LookUpAura(unitId, magicImmuneDebuffList, 2) or LookUpAura(unitId, magicImmuneBuffList, 1)
end

function bit_(p)
  return 2 ^ (p - 1)  -- 1-based indexing
end

-- Typical call:  if hasbit(x, bit(3)) then ...
function hasbit(x, p)
  return x % (p + p) >= p       
end

